package whf.framework.util;

import java.util.Map;

import javax.servlet.ServletContext;
import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import whf.framework.config.ApplicationConfig;
import whf.framework.dao.DAO;
import whf.framework.exception.ServiceNotFoundException;
import whf.framework.i18n.ApplicationResource;
import whf.framework.log.Log;
import whf.framework.log.LogFactory;
import whf.framework.meta.Meta;
import whf.framework.meta.MetaFactory;
import whf.framework.service.Service;

/**
 * @author wanghaifeng
 *
 */
@SuppressWarnings("unchecked")
public class BeanFactory {
	private static Log log = LogFactory.getLog(BeanFactory.class);
	
	/**
	 * 如果存在则是获取web环境下的SpringContext
	 * @property ServletContext:servletContext
	 */
	private static ServletContext servletContext;

	private static ApplicationContext springContext;
	
	private final static Map<String, String> beanNames = Utils.newHashMap();

	public final static void registerBean(String className, String beanName){
		log.debug("Register bean:\tClass name:"+className+"\t beanName:"+beanName);
		beanNames.put(className, beanName);
	}
	
	public static void setServletContext(ServletContext context) {
		if(context != null && !StringUtils.isEmpty(context.getInitParameter("contextConfigLocation"))){
			servletContext = context;
			springContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		}
	}
	
	public static Object getBean(Class serviceClass){
		if (springContext == null) {
			synchronized(BeanFactory.class) {
				springContext = new ClassPathXmlApplicationContext(ApplicationConfig.getInstance().getSpringConfigurationFiles());
			}
		}
		String serviceName = beanNames.get(serviceClass.getName());
		if(serviceName.toUpperCase().endsWith("TARGET")){
			serviceName = serviceName.substring(0, serviceName.length() - 6);
		}
		return getBean(serviceName);
	}

	/**
	 * 从spring容器中获取bean实例对象
	 * @param name
	 * @return
	 */
	public static Object getBean(String name) {
		log.debug("get bean:"+name + " @@\n");
		if (springContext == null) {
			synchronized(BeanFactory.class) {
				springContext = new ClassPathXmlApplicationContext(ApplicationConfig.getInstance().getSpringConfigurationFiles());
			}
		}
		Object bean = springContext.getBean(name);
		if(bean == null){
			log.warn(ApplicationResource.get("exception.service_not_found", name));
		}
		return bean;
	}
	
	public static SessionFactory getSessionFactory(){
		return (SessionFactory)getBean("sessionFactory");
	}
	
	public static DataSource getDataSource(){
		return (DataSource)BeanFactory.getBean("dataSource");
	}
	
	public static Service getService(String serviceName) throws ServiceNotFoundException{
		Meta meta = MetaFactory.findByServiceName(serviceName);
		ThreadContext.setCurrentMeta(meta);
		try{
			Service service = (Service)getBean(serviceName);
			if (service == null){
				throw new ServiceNotFoundException(ApplicationResource.get("exception.service_not_found",serviceName));
			}
			return service;
		}catch(Exception e){
			log.error("getService():"+serviceName, e);
			throw new ServiceNotFoundException(e, serviceName);
		}
	}
	
	public final static Service getService(Class serviceClass) throws ServiceNotFoundException{
		Meta meta = MetaFactory.findByServiceClass(serviceClass);
		ThreadContext.setCurrentMeta(meta);
		return (Service)getBean(serviceClass);
	}
	
	public static Service getService(Meta meta) throws ServiceNotFoundException{
		ThreadContext.setCurrentMeta(meta);
		return getService(meta.getServiceName());
	}
	
	public final static DAO getDao(Class daoClass) throws ServiceNotFoundException{
		String serviceName = beanNames.get(daoClass.getName());
		if(serviceName.toUpperCase().endsWith("TARGET")){
			serviceName = serviceName.substring(0, serviceName.length() - 6);
		}
		serviceName = serviceName.substring(0, serviceName.length() - 7);
		String daoName = serviceName+"DAO";
		DAO dao = null;
		try{
			dao = getDao(daoName);
		}catch(Exception e){
			dao = getDao(MetaFactory.findByServiceClass(daoClass));
		}
		return dao;
	}
	
	public static DAO getDao(String daoName) throws ServiceNotFoundException{
		try{
			DAO dao = (DAO)getBean(daoName);
			if (dao == null){
				throw new ServiceNotFoundException(ApplicationResource.get("exception.service_not_found",daoName));
			}
			return dao;
		}catch(Exception e){
			log.error("getDao():"+daoName, e);
			throw new ServiceNotFoundException(e, daoName);
		}
	}
	
	public static DAO getDao(Meta meta) throws ServiceNotFoundException{
		return getDao(meta.getDaoName());
	}
	
	/**
	 * 是否存在于web环境
	 * @modify wanghaifeng Aug 26, 2006 12:14:34 PM
	 * @return
	 */
	public static boolean inWebModule(){
		return servletContext != null;
	}
	
	public static boolean hadInitialized(){
		return springContext != null;
	}
	
	public static void main(String args[]) throws Exception{
//		getSessionFactory();
//		System.out.println(getDao(ObjectServiceImp.class));
		System.out.println(BeanFactory.getBean("dataSource"));
	}
	
}
